import crypto from 'crypto'
import UUID from 'uuid'
// #ifdef APP-PLUS
import { gotoAppPermissionSetting, requestAndroidPermission } from "./permission.js"
const isIos = (plus.os.name == "iOS")
// #endif
import {
	Bucket,
	Region,
	storageKey,
	uniConfig
} from './constant.js'
import {
	ajax,
	request,
	defaultAfter
} from './ajax.js'
import * as cache from "@/utils/storage.js"
import { getBaseUrl } from '@/utils/config.js'
// #ifdef H5
import { toast } from './util.js'
// #endif

export const expires = 60; 

const getCredentials = (header) => {
	return ajax({
		url:"/qcloud/sessionCredentialsV2",
		header
	})
	
}

const isBase64 = (base='') =>{
	return base.includes("base64")
}

const getBaseExt = (base='')=>{
	const t1 = base.split(';').shift()
	const t2 = t1.split('/').pop()
	if(t2=='jpg'||t2=='jpeg'){
		return "jpg"
	}
	if(t2=='png'){
		return 'png'
	}
	return t2
}


const getPostPolicy = ({
	sessionToken,
	tmpSecretId,
	tmpSecretKey
}) => {
	const currentDate = new Date();
	const expirationDate = new Date(currentDate.getTime() + expires * 1000);
	const keyTime = `${Math.floor(currentDate.getTime() / 1000)};${Math.floor(expirationDate.getTime() / 1000)}`;
	const policy = JSON.stringify({
		expiration: expirationDate.toISOString(),
		conditions: [{
				'q-sign-algorithm': 'sha1'
			},
			{
				'q-ak': tmpSecretId
			},
			{
				'q-sign-time': keyTime
			}
		],
	});
	const signKey = crypto.createHmac('sha1', tmpSecretKey).update(keyTime).digest('hex');
	const stringToSign = crypto.createHash('sha1').update(policy).digest('hex');
	const signature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex');
	return {
		host: `https://${Bucket}.cos.${Region}.myqcloud.com`,
		signAlgorithm: 'sha1',
		ak: tmpSecretId,
		keyTime,
		signature,
		policy: Buffer.from(policy).toString('base64'),
		sessionToken
	}
}

const getCloudPath =(fileName)=>{
	return `https://${Bucket}.cos.${Region}.myqcloud.com/${fileName}`;
}

export const base64ToPath = (base64) => {
    return new Promise(function(resolve, reject) {
        if (typeof window === 'object' && 'document' in window) {
            base64 = base64.split(',')
            var type = base64[0].match(/:(.*?);/)[1]
            var str = atob(base64[1])
            var n = str.length
            var array = new Uint8Array(n)
            while (n--) {
                array[n] = str.charCodeAt(n)
            }
            return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
        }
        var extName = base64.match(/data\:\S+\/(\S+);/)
        if (extName) {
            extName = extName[1]
        } else {
            reject(new Error('base64 error'))
        }
        var fileName = Date.now() + '.' + extName
        if (typeof plus === 'object') {
            var bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
            bitmap.loadBase64Data(base64, function() {
                var filePath = '_doc/uniapp_temp/' + fileName
                bitmap.save(filePath, {}, function() {
                    bitmap.clear()
                    resolve(filePath)
                }, function(error) {
                    bitmap.clear()
                    reject(error)
                })
            }, function(error) {
                bitmap.clear()
                reject(error)
            })
            return
        }
        if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
            var filePath = wx.env.USER_DATA_PATH + '/' + fileName
            wx.getFileSystemManager().writeFile({
                filePath: filePath,
                data: base64.replace(/^data:\S+\/\S+;base64,/, ''),
                encoding: 'base64',
                success: function() {
                    resolve(filePath)
                },
                fail: function(error) {
                    reject(error)
                }
            })
            return
        }
        reject(new Error('not support'))
    })
}

export const cloudUpload = async ({
	file,
	pre = '',
	key,
	onProgressUpdate
},header) => {
	try {
		if (!file) {
			throw new Error('file不能为空');
		}
		// #ifndef H5
		if (typeof file !== 'string') {
			file = file.path;
		}
		// #endif
		// #ifdef APP-PLUS
		 file = await formatHEIC(file)
		// #endif
		const {
			credentials
		} = await getCredentials(header);
		const signData = getPostPolicy(credentials);
		return new Promise(async (resolve, reject) => {
			let filePath = undefined;
			let fileExt;
			if (typeof file === 'string') {
				if(isBase64(file)){
					fileExt = getBaseExt(file)
					filePath = await base64ToPath(file);
				}else{
					filePath = file;
					fileExt = filePath.split('?')[0].split('.').pop();
				}
				file = undefined;
			} else {
			  fileExt = file.name.split('.').pop();
			}
			
			
			let fileType = undefined;
			
			fileType = getMediaType(fileExt);
			
			if (!key) {
				key = `${UUID.v1()}.${fileExt}`;
			}
			key = pre ? pre + key : key;
			const uploadTask = uni.uploadFile({
				url: signData.host,
				file,
				filePath,
				fileType,
				name: 'file',
				formData: {
					key,
					'q-sign-algorithm': signData.signAlgorithm,
					'q-ak': signData.ak,
					'q-key-time': signData.keyTime,
					'q-signature': signData.signature,
					'policy': signData.policy,
					'x-cos-security-token': signData.sessionToken
				},
				success(response) {
					if (+response.statusCode !== 204) {
						reject(new Error('文件上传失败'));
					} else {
						resolve(getCloudPath(key));
					}
				},
				fail(error) {
					
					if (+error.statusCode === 204) {
						resolve(getCloudPath(key));
					} else {
						reject(error);
					}
				}
			});
			onProgressUpdate && uploadTask.onProgressUpdate(onProgressUpdate);
		})
	} catch (e) {
		throw e
	}
}

export const localUpload = async ({
	file,
	onProgressUpdate
},header)=>{
	try{
		console.log('服务器本地上传')
		if (!file) {
			throw new Error('file不能为空');
		}
		// #ifndef H5
		if (typeof file !== 'string') {
			file = file.path;
		}
		// #endif
		// #ifdef APP-PLUS
		 file = await formatHEIC(file)
		// #endif
		const token = await cache.get(storageKey.token)
		const uploadRes = await new Promise(async(resolve, reject) => {
			let filePath = undefined;
			let fileExt;
			if (typeof file === 'string') {
			  if(isBase64(file)){
			  	fileExt = getBaseExt(file)
			  	filePath = await base64ToPath(file);
			  }else{
			  	filePath = file;
			  	fileExt = filePath.split('?')[0].split('.').pop();
			  }
			  file = undefined;
			} else {
			  fileExt = file.name.split('.').pop();
			}
			
			
			let fileType = undefined;
			
			fileType = getMediaType(fileExt);
			
			const uploadTask = uni.uploadFile({
				url: `${getBaseUrl()}/sysFileUpload/upload`,
				file,
				filePath,
				fileType,
				name: "file",
				header: {
					token,
					...header
				},
				success: resolve,
				fail: reject
			});
			onProgressUpdate && uploadTask.onProgressUpdate(onProgressUpdate);
		});
		uploadRes.data = JSON.parse(uploadRes.data)
		const {filePath} = await defaultAfter(uploadRes, {})
		return filePath
	}catch(e){
		throw e
	}
}

let myCloud = null
export const uniUpload = async({
	file,
	pre='',
	onProgressUpdate
},header)=>{
	console.log('uni云上传')
	if(!myCloud){
		myCloud = uniCloud.init(uniConfig);
	}
	
	// #ifndef H5
	if (typeof file !== 'string') {
		file = file.path;
	}
	// #endif
	// #ifdef APP-PLUS
	file = await formatHEIC(file)
	// #endif
	return new Promise(async (resolve,reject)=>{
		let cloudPath = ''
		if (typeof file === 'string') {
			if(isBase64(file)){
				const fileExt = getBaseExt(file)
				cloudPath = Date.now()+'.'+fileExt;
				file = await base64ToPath(file);
			}else{
				const fileExt = file.split('?')[0].split('.').pop();
				cloudPath = file.split('?')[0].split('/').pop();
			}
		}else{
			cloudPath = file.name;
			// #ifdef H5
			file = file.path
			// #endif
		}
		myCloud.uploadFile({
			filePath:file,
			cloudPath:pre+cloudPath,
			onUploadProgress({loaded,total}){
				onProgressUpdate&&onProgressUpdate({
					progress:Math.ceil(loaded*100/total),
					totalBytesSent:loaded,
					totalBytesExpectedToSend:total
				})
			},
			success({fileID}){
				resolve(fileID)
			},
			fail:reject
		})
	})
}

export const previewImage = ({
	current = 0,
	urls,
	indicator = 'default',
	loop = false
}) => {
	uni.previewImage({
		current,
		urls,
		indicator,
		loop
	})
}
export const chooseImage = async (options) => {
	// #ifdef APP-PLUS
	if(!isIos){
		let source = '' 
		if(!options.sourceType||options.sourceType.length>1){
			source = await new Promise((resolve,reject)=>{
				uni.showActionSheet({
					itemList:['拍摄','从相册选择'],
					success({tapIndex}) {
						switch (tapIndex){
							case 0:
								resolve('camera')
								break;
							case 1:
								resolve('album')
								break;
						}
					},
					fail:reject
				})
			})
		}else{
			source = options.sourceType[0]
		}
		let permission = 1
		if(source=='album'){
			var androad13 = false;
			// #ifdef APP-PLUS
			if(plus.os.name == 'Android'){
				var Build = plus.android.importClass("android.os.Build");
				if (Build.VERSION.SDK_INT >= 33) {
				    androad13 = true;
				}else{
					androad13 = false;                      
				}
			}
			// #endif
			if(!androad13)permission = await requestAndroidPermission('android.permission.READ_EXTERNAL_STORAGE')
		}
		if(source=='camera'){
			permission = await requestAndroidPermission('android.permission.CAMERA')
		}
		if(permission==0){
			
			return 
		}
		if(permission==-1){
			uni.showModal({  
				title: '提示',  
				content: '操作权限已被拒绝，请手动前往设置',  
				confirmText: "立即设置",  
				success: ({confirm}) => {  
					confirm&&gotoAppPermissionSetting()
				}  
			}) 
			return
		}
		options = {...options,sourceType:[source]}
	}
	// #endif
	return new Promise((resolve, reject) => {
		uni.chooseImage({
			...options,
			success:resolve,
			fail:reject
		})
	})
}
export const chooseVideo = async (options) => {
	// #ifdef APP-PLUS
	if(!isIos){
		let source = '' 
		if(!options.sourceType||options.sourceType.length>1){
			source = await new Promise((resolve,reject)=>{
				uni.showActionSheet({
					itemList:['拍摄','从相册选择'],
					success({tapIndex}) {
						switch (tapIndex){
							case 0:
								resolve('camera')
								break;
							case 1:
								resolve('album')
								break;
						}
					},
					fail:reject
				})
			})
		}else{
			source = options.sourceType[0]
		}
		let permission = 1
		if(source=='album'){
			permission = await requestAndroidPermission('android.permission.READ_EXTERNAL_STORAGE')
		}
		if(source=='camera'){
			permission = await requestAndroidPermission('android.permission.CAMERA')
		}
		if(permission==0){
			
			return 
		}
		if(permission==-1){
			
			uni.showModal({  
				title: '提示',  
				content: '操作权限已被拒绝，请手动前往设置',  
				confirmText: "立即设置",  
				success: ({confirm}) => {  
					confirm&&gotoAppPermissionSetting()
				}  
			}) 
			return
		}
		options = {...options,sourceType:[source]}
	}
	// #endif
	return new Promise((resolve, reject) => {
		uni.chooseVideo({
			...options,
			success(res) {
				// #ifdef H5
				res.tempFile.path = res.tempFilePath
				// if( !/^video\
				// 	reject(new Error('文件类型错误'))
				// 	return toast('文件类型错误')
				// }
				// #endif
				resolve(res);
			},
			fail(e) {
				reject(e);
			}
		})
	})
}
export const getImageInfo = async (options) => {
	return new Promise((resolve, reject) => {
		uni.getImageInfo({
			...options,
			success(res) {
				resolve(res);
			},
			fail(e) {
				reject(e);
			}
		})
	})
}
export const saveImage = async (options)=>{
	return new Promise((resolve,reject)=>{
		uni.saveImageToPhotosAlbum({
			...options,
			success:resolve,
			fail:reject
		})
	})
}
export const scanCode = async (options)=>{
	// #ifdef APP-PLUS
	if(!isIos){
		let permission = await requestAndroidPermission('android.permission.CAMERA')
		if(permission==0){
			
			throw new Error('用户放弃了授权') 
		}
		if(permission==-1){
			
			uni.showModal({  
				title: '提示',  
				content: '操作权限已被拒绝，请手动前往设置',  
				confirmText: "立即设置",  
				success: ({confirm}) => {  
					confirm&&gotoAppPermissionSetting()
				}  
			}) 
			throw new Error('用户禁止了授权')
		}
	}
	// #endif
	return new Promise((resolve,reject)=>{
		uni.scanCode({
			...options,
			success:resolve,
			fail:reject
		})
	})
}


export const compressImage = (options)=>{
	return new Promise((resolve,reject)=>{
		// #ifdef H5
		resolve({tempFilePath:options.src})
		// #endif
		// #ifndef H5
		uni.compressImage({
			...options,
			success:resolve,
			fail:reject
		})
		// #endif
	})
}

export const videoAdvance = (filePath)=>{
	let smallUrl = ''
	if(uploadFile.canal=='4'){
		smallUrl = filePath.concat('?x-oss-process=video/snapshot,t_1000,f_jpg,w_0,h_0,m_fast,ar_auto')
	}else{
		const slashLast = filePath.lastIndexOf('/')
		const dotLast = filePath.lastIndexOf('.')
		smallUrl = filePath.slice(0,slashLast)+'/small'+filePath.slice(slashLast,dotLast)+'.jpg'
		
		ajax({
			url: '/dynamicMedia/pushMedia',
			data: {
				mediaUrl: filePath,
				type:2
			}
		})
	}
	return smallUrl
}

export const videoDelay = ({type,mediaUrl})=>{
	if(uploadFile.canal=='4'){
		ajax({
			url: '/dynamicMedia/pushMedia',
			data: {
				mediaUrl,
				type
			}
		})
	}
}

export const compressVideo = (options)=>{
	return new Promise((resolve,reject)=>{
		// #ifdef H5
		resolve({tempFilePath:options.src})
		// #endif
		// #ifndef H5
		uni.compressVideo({
			...options,
			success:resolve,
			fail:reject
		})
		// #endif
	})
}

export const uploadFile = async ({
	file,
	pre = '',
	key,
	onProgressUpdate
},header) => {		
	try {
		if(uploadFile.canal=='2'){
			return cloudUpload({file,pre,key,onProgressUpdate},header)
		}else if(uploadFile.canal=='1'){
			return localUpload({file,pre,key,onProgressUpdate},header)
		}else if(uploadFile.canal=='4'){
			return uniUpload({file,onProgressUpdate},header)
		}
	} catch (error) {
		throw error;
	}
}
uploadFile.canal = '1'

export const downloadFile = async ({url,onProgressUpdate,...rest}) =>{
	if(!url){
		throw new Error('请求地址不能为空')
	}
	return new Promise((resolve,reject)=>{
		const downloadTask = uni.downloadFile({
			url,
			...rest,
			success({tempFilePath,statusCode}) {
				if(statusCode==200){
					resolve(tempFilePath)
				}else{
					reject(new Error('下载失败'))
				}
			},
			fail:reject
		})
		const abort = ()=>{
			downloadTask.abort()
		}
		downloadTask.onProgressUpdate((res)=>{
			!!onProgressUpdate&&onProgressUpdate(res,abort)
		})
	})
}


export const compress = (filePath, type) => {
	let path1 = filePath.substring(0, filePath.lastIndexOf('/') + 1) + 'small/' + filePath.substring(filePath.lastIndexOf('/') + 1);
	let path2 = path1.substring(0, path1.lastIndexOf('.')) + '.jpg';
	const smallUrl = `${type===2?path2:path1}`
	ajax({
		url: '/dynamicMedia/pushMedia',
		data: {
			mediaUrl: filePath,
			type
		}
	})
	return smallUrl;
}

export const formatHEIC = (filePath) => {
	return new Promise((resolve,reject)=>{
		const regex = /.HEIC$/i;
		if(!regex.test(filePath)){
			return resolve(filePath)
		}
		plus.zip.compressImage(
			{
				src:filePath,
				dst:filePath.replace(regex,'.jpg'),
				quality:100,
				format:"jpg"	
			},
			({target})=>{
				resolve(target)
			},
			reject
		)
	})
}

export const getMediaType = (ext) => {
	if (/^(jpg|jpeg|png|gif|bmp|webp)$/.test(ext.toLowerCase())) {
		return 'image';
	}
	if (/^(mp4|mpeg|qsv|mov|avi|3gp)$/.test(ext.toLowerCase())) {
		return 'video';
	}
	if (/^(mp3|wma|wav|m4a)$/.test(ext.toLowerCase())) {
		return 'audio';
	}
	return 'other';
}

